#include "stdafx.h"
//#include <cstdlib>
//#include <ctime>
//#include <string>
#include <iostream>

//#include "common.h"
//#include "Config.h" // Reading configuration file
//#include "lyxDef.h" // Typedefs(UlLong, Doub, UInt)
//#include "CNDArray.h"
//#include "CMatFile.h" // Matlab MAT-file processor
//#include "ran.h" // Numerical Recipes v3.0

 using namespace std;

 class Grid{
 public:
	 Grid(){}
	 Grid(Grid &rhs){
	/*	 _Lx=rhs.Lx();_Ly=rhs.Ly();_Lz=rhs.Lz();_data=(*rhs.data());*/
	 }
	 /*Grid(const string name,const Config &cfg):_name(name),_seed(0)
	 {init(cfg);set_value(0.0);}
	 Grid(const string name,const Config &cfg,const double 
		 val):_name(name),_seed(0){init(cfg);set_value(val);}
	 Grid(const string name,const Config &cfg,const NRMat3d<double> 
		 &data):_name(name),_seed(0){init(cfg);set_value(data);}
	 Grid(const string name,const Config &cfg,const string file):_name(name),_seed(0)
	 {init(cfg);set_value(file);}
	 Grid(const string name,const Config &cfg,const double low,const double 
		 high,const size_t seed=0):_name(name){init(cfg);set_value(seed,low,high);}
	 NRMat3d<double> *data(){return &_data;}
	 */
	 //double & operator() (int ix,int iy, int iz){return _data[ix][iy][iz];}
	 // this hides the complicated internal structure of array for 2D space.
	 //double & operator() (int iy, int iz){return _data[0][iy][iz];}
	 //double & operator() (int iz){return _data[0][0][iz];}
	 Grid & operator+= (Grid &);
	 Grid & operator+= (const double);
	 Grid & operator-= (Grid &);
	 Grid & operator-= (const double);
	 Grid & operator*= (Grid &);
	 Grid & operator*= (const double);
	 void save(string file);
	 string name() const{return _name;}
	 void set_name(const string name){_name=name;}
	 int dim() const{return _dim;}
	 int Lx() const{return _Lx;}
	 int Ly() const{return _Ly;}
	 int Lz() const{return _Lz;}
	 double lx() const{return _lx;}
	 double ly() const{return _ly;}
	 double lz() const{return _lz;}
	 double dx() const{return _lx/_Lx;}
	 double dy() const{return _ly/_Ly;}
	 double dz() const{return _lz/_Lz;}
	 double mean() const;
	 double min() const;
	 double max() const;
	 int ngrids() const{return _Lx*_Ly*_Lz;}
	 double volume() const{return _lx*_ly*_lz;}
	 size_t seed() const{return _seed;}
	 virtual void update(){}

 private:
	 string _name;
	 int _dim; // actual space dimension
	 int _Lx,_Ly,_Lz; // 1D: _Lx=1; 2D: _Lx=_Ly=1
	 double _lx,_ly,_lz;
	 //GridType _grid_type;
	 //GridInitType _grid_init_type;
	 //NRMat3d<double> _data;
	 double _data;
	 size_t _seed;

	 //void init(const Config &cfg);
	 /*void set_value(const double val);
	 void set_value(const NRMat3d<double> &data);
	 void set_value(string file);
	 void set_value(const size_t seed,const double low,const double high);*/
 };

 Grid operator+ (Grid &,Grid &);
 Grid operator+ (const double,Grid &);
 Grid operator+ (Grid &,const double);
 Grid operator- (Grid &,Grid &);
 Grid operator- (const double,Grid &);
 Grid operator- (Grid &,const double);
 Grid operator* (Grid &,Grid &);
 Grid operator* (const double,Grid &);
 Grid operator* (Grid &,const double);

//#endif
//
// Grid.cpp
//#include "Grid.h"

	// void Grid::save(string file){
	//	 CMatFile mat;
	//	 mwSize dims3[3]={_Lx,_Ly,_Lz};

	//	 mat.matInit(file.c_str(),"u");
	//	 if(!mat.queryStatus()){

	//		 mat.matPut(_name,_data.getRaw(),_data.sizeByte(),3,dims3,mxDOUBLE_CLASS,mxR
	//			 EAL);
	//	 }
	//	 else{
	//		 cout<<"error: cannot open MAT-file: "<<_name<<endl;
	//	 }
	//	 mat.matRelease();
 //}

 //double Grid::mean() const{
	// double sum=0.0;
	// for(int i=0;i<_Lx;i++)
	//	 for(int j=0;j<_Ly;j++)
	//		 for(int k=0;k<_Lz;k++)
	//			 sum += _data[i][j][k];
	// return sum/ngrids();
 //}

 //double Grid::min() const{
	// double m=_data[0][0][0];
	// for(int i=0;i<_Lx;i++)
	//	 for(int j=0;j<_Ly;j++)
	//		 for(int k=0;k<_Lz;k++)
	//			 if(_data[i][j][k]<m) m=_data[i][j][k];
	// return m;
 //}

 //double Grid::max() const{
	// double m=_data[0][0][0];
	// for(int i=0;i<_Lx;i++)
	//	 for(int j=0;j<_Ly;j++)
	//		 for(int k=0;k<_Lz;k++)
	//			 if(_data[i][j][k]>m) m=_data[i][j][k];
	// return m;
 //}

 //void Grid::init(const Config &param){
	// _dim=param.get_integer("Grid","dimension");
	// _Lx=param.get_integer("Grid","Lx");
	// _Ly=param.get_integer("Grid","Ly");
	// _Lz=param.get_integer("Grid","Lz");
	// _lx=param.get_double("Grid","llx");
	// _ly=param.get_double("Grid","lly");
	// _lz=param.get_double("Grid","llz");
	// _grid_type=param.get_grid_type();
	// _grid_init_type=param.get_grid_init_type();
 //}

 //void Grid::set_value(const double val){
	// _data.resize(_Lx,_Ly,_Lz);
	// for(int i=0;i<_Lx;i++)
	//	 for(int j=0;j<_Ly;j++)
	//		 for(int k=0;k<_Lz;k++)
	//			 _data[i][j][k]=val;
 //}

 //void Grid::set_value(const NRMat3d<double> &data){
	// _data=data;
 //}

 //void Grid::set_value(const string file){
	// CMatFile mat;
	// _data.resize(_Lx,_Ly,_Lz);
	// mat.matInit(file,"r");
	// if(!mat.queryStatus()){
	//	 mat.matGetArray(_name,_data.getRaw(),_data.sizeByte());
	//	 mat.matRelease();
	// }
	// else{
	//	 cout<<"error: cannot read file: "<<file<<endl;
	// }
 //}

 //void Grid::set_value(const size_t seed,const double low,const double high){
	// _data.resize(_Lx,_Ly,_Lz);
	// if(!seed)
	//	 _seed=static_cast<size_t> (time(NULL)+clock());
	// else
	//	 _seed=seed;
	// Ran *pran=new Ran(_seed);
	// double range=high-low;
	// for(int i=0;i<_Lx;i++)
	//	 for(int j=0;j<_Ly;j++)
	//		 for(int k=0;k<_Lz;k++)
	//			 _data[i][j][k]=low+range*pran->doub();
 //}

 Grid & Grid::operator+= (Grid &rhs){
	 //for(int i=0;i<_Lx;i++)
		// for(int j=0;j<_Ly;j++)
		//	 for(int k=0;k<_Lz;k++)
		//		 _data[i][j][k] += rhs(i,j,k);
	 return *this;
 }

 Grid & Grid::operator+= (const double rhs){
	 //for(int i=0;i<_Lx;i++)
		// for(int j=0;j<_Ly;j++)
		//	 for(int k=0;k<_Lz;k++)
		//		 _data[i][j][k] += rhs;
	 return *this;
 }

 Grid & Grid::operator-= (Grid &rhs){
	 //for(int i=0;i<_Lx;i++)
		// for(int j=0;j<_Ly;j++)
		//	 for(int k=0;k<_Lz;k++)
		//		 _data[i][j][k] -= rhs(i,j,k);
	 return *this;
 }

 Grid & Grid::operator-= (const double rhs){
	 //for(int i=0;i<_Lx;i++)
		// for(int j=0;j<_Ly;j++)
		//	 for(int k=0;k<_Lz;k++)
		//		 _data[i][j][k] -= rhs;
	 return *this;
 }

 Grid & Grid::operator*= (Grid &rhs){
	 //for(int i=0;i<_Lx;i++)
		// for(int j=0;j<_Ly;j++)
		//	 for(int k=0;k<_Lz;k++)
		//		 _data[i][j][k] *= rhs(i,j,k);
	 return *this;
 }

 Grid & Grid::operator*= (const double rhs){
	 //for(int i=0;i<_Lx;i++)
		// for(int j=0;j<_Ly;j++)
		//	 for(int k=0;k<_Lz;k++)
		//		 _data[i][j][k] *= rhs;
	 return *this;
 }

 Grid operator+ (Grid &lhs,Grid &rhs){
	 Grid tmp(lhs);
	 tmp += rhs;
	 return tmp;
 }

 Grid operator+ (const double lhs,Grid &rhs){
	 Grid tmp(rhs);
	 tmp += lhs;
	 return tmp;
 }

 Grid operator+ (Grid &lhs,const double rhs){
	 Grid tmp(lhs);
	 tmp += rhs;
	 return tmp;
 }

 Grid operator- (Grid &lhs,Grid &rhs){
	 Grid tmp(lhs);
	 tmp -= rhs;
	 return tmp;
 }

 Grid operator- (const double lhs,Grid &rhs){
	 Grid tmp(rhs);
	 //for(int i=0;i<rhs.Lx();i++)
		// for(int j=0;j<rhs.Ly();j++)
		//	 for(int k=0;k<rhs.Lz();k++)
		//		 tmp(i,j,k)=lhs-tmp(i,j,k);
	 return tmp;
 }

 Grid operator- (Grid &lhs,const double rhs){
	 Grid tmp(lhs);
	 tmp -= rhs;
	 return tmp;
 }

 Grid operator* (Grid &lhs,Grid &rhs){
	 Grid tmp(lhs);
	 tmp *= rhs;
	 return tmp;
 }

 Grid operator* (const double lhs,Grid &rhs){
	 Grid tmp(rhs);
	 tmp *= lhs;
	 return tmp;
 }

 Grid operator* (Grid &lhs,const double rhs){
	 Grid tmp(lhs);
	 tmp *= rhs;
	 return tmp;
 }


#include <iostream>
#include <string>

//#include "../Config.h"
//#include "../common.h"
//#include "../Grid.h"

using namespace std;

 //void test_config(){
	// Config cfg("param.ini");

	// cout<<"Begin Config test..."<<endl;
	// cout<<"Successfully loaded? "<<cfg.is_empty()<<endl;
	// cout<<"dimension = "<<cfg.get_integer("Grid","dimension")<<endl;
	// cout<<"Lx = "<<cfg.get_integer("Grid","Lx")<<endl;
	// cout<<"Ly = "<<cfg.get_integer("Grid","Ly")<<endl;
	// cout<<"Lz = "<<cfg.get_integer("Grid","Lz")<<endl;
	// cout<<"lx = "<<cfg.get_double("Grid","llx")<<endl;
	// cout<<"ly = "<<cfg.get_double("Grid","lly")<<endl;
	// cout<<"lz = "<<cfg.get_double("Grid","llz")<<endl;
	// cout<<"GridType = "<<GridTypes[cfg.get_grid_type()]<<endl;
	// cout<<"GridInitType = "<<GridInitTypes[cfg.get_grid_init_type()]<<endl;
	// cout<<"PhasePattern = "<<PhasePatterns[cfg.get_phase_pattern()]<<endl;
	// cfg.save("cfg.ini.bak");
	// cfg.clear();
	// cout<<"Successfully cleared? "<<cfg.is_empty()<<endl;
	// cout<<endl;
 //}

 //void test_grid(){
	// Config cfg("param.ini");

	// Grid wA("wA",cfg,1234,-0.05,0.05);
	// cout<<"Begin Grid test..."<<endl;
	// cout<<"Grid Name: "<<wA.name()<<endl;
	// cout<<"(Lx,Ly,Lz) = "<<"("<<wA.Lx()<<","<<wA.Ly()<<","<<wA.Lz()<<")"
	//	 <<endl;
	// cout<<"(lx,ly,lz) = "<<"("<<wA.lx()<<","<<wA.ly()<<","<<wA.lz()<<")"<<endl;
	// cout<<"(dx,dy,dz) = "<<"("<<wA.dx()<<","<<wA.dy()<<","<<wA.dz()<<")"
	//	 <<endl;
	// cout<<"(mean,min,max) = "<<"("<<wA.mean()<<","<<wA.min()<<","
	//	 <<wA.max()<<")"<<endl;
	// cout<<"number of grids = "<<wA.ngrids()<<endl;
	// cout<<"grid volume = "<<wA.volume()<<endl;
	// cout<<"random seed = "<<wA.seed()<<endl;
	// wA.save("data.mat");

	// Grid wB("wB",cfg,5678,-0.05,0.05);
	// cout<<"wB[0][1][1] = "<<wB(0,1,1)<<endl;
	// wB(0,1,1)=0.0; // should be 0
	// cout<<"wB[0][1][1] = (0) "<<wB(0,1,1)<<endl;
	// wB(0,1,1)=wB(0,1,1)+1; // should be 1
	// cout<<"wB[0][1][1] = (1) "<<wB(0,1,1)<<endl;
	// wB(1,1) +=999.0; // should be 1000
	// cout<<"wB[0][1][1] = (1000) "<<wB(0,1,1)<<endl;
	// wB(1,1)++; // should be 1001;
	// cout<<"wB[0][1][1] = (1001) "<<wB(0,1,1)<<endl;
	// wB.save("data.mat");
	// cout<<endl;

	// // convert an pointer to a reference
	// // succeed
	// Grid *pwC;
	// pwC=new Grid("wC",cfg,999.0);
	// Grid &wC=(*pwC);
	// cout<<"pwC = "<<pwC<<endl;
	// cout<<"&wC = "<<&wC<<endl;
	// wC(1,1)=1.0;
	// wC.save("data.mat");
	// cout<<endl;

	// // overloaded arithmetic operator
	// // + - * for Grid Grid passed
	// // + - * for double Grid  passed
	// // + - * for Grid double passed
	// Grid wD("wD",cfg,3.0);
	// Grid wE("wE",cfg,2.0);
	// Grid wF,wG,wH;
	// wF=7+wD;
	// cout<<"wF.mean = (10) "<<wF.mean()<<endl;
	// wF.set_name("wF");
	// cout<<"wF.name = "<<wF.name()<<endl;
	// wF.save("data.mat");
	// wG=7-wD;
	// cout<<"wG.mean = (4) "<<wG.mean()<<endl;
	// wG.set_name("wG");
	// cout<<"wG.name = "<<wG.name()<<endl;
	// wG.save("data.mat");
	// wH=7*wD;
	// cout<<"wH.mean = (21) "<<wH.mean()<<endl;
	// wH.set_name("wH");
	// cout<<"wH.name = "<<wH.name()<<endl;
	// wH.save("data.mat");
	// cout<<endl;

	// // +=, -=, *= for Grid passed
	// // +=, -=, *= for double passed
	// Grid wI("wI",cfg,9.0);
	// Grid wJ("wJ",cfg,9.0);
	// Grid wK("wK",cfg,9.0);
	// Grid wL("wL",cfg,6.0);
	// wI+=wL;
	// cout<<"wI.mean = (15) "<<wI.mean()<<endl;
	// cout<<"wI.name = "<<wI.name()<<endl;
	// wI.save("data.mat");
	// wJ-=wL;
	// cout<<"wJ.mean = (3) "<<wJ.mean()<<endl;
	// cout<<"wJ.name = "<<wJ.name()<<endl;
	// wJ.save("data.mat");
	// wK*=wL;
	// cout<<"wK.mean = (54) "<<wK.mean()<<endl;
	// cout<<"wK.name = "<<wK.name()<<endl;
	// wK.save("data.mat");
	// cout<<endl;

	// // arithmetic combinations
	// Grid wM("wM",cfg,4.0);
	// Grid wN("wN",cfg,5.0);
	// Grid wO("wO",cfg,6.0);
	// Grid wP("wP",cfg,7.0);
	// Grid wQ;
	// wQ=wM+wN+wO;
	// //wQ=1+3*wM-2*wN*wN+3*(wO+wP);
	// cout<<"wQ.mean = (15) "<<wQ.mean()<<endl;
	// wQ.set_name("wQ");
	// cout<<"wQ.name = "<<wQ.name()<<endl;
	// wQ.save("data.mat");
	// cout<<endl;
 //}

 int main(){
	 //test_config();
	 //test_grid();

	/* Grid wM("wM",cfg,4.0);
	 Grid wN("wN",cfg,5.0);
	 Grid wO("wO",cfg,6.0);
	 Grid wP("wP",cfg,7.0);*/

	 Grid wM,wN,wO,wP,wQ;
	 wQ=wM+wN+wO;
	 //wQ=1+3*wM-2*wN*wN+3*(wO+wP);
	 return 0;
 }


 